Feat: add BaseSessionService.flush() and drain it from the Runner (adk-python parity) - #818
Open
AmaadMartin wants to merge 2 commits into
Open
Feat: add BaseSessionService.flush() and drain it from the Runner (adk-python parity)#818AmaadMartin wants to merge 2 commits into
AmaadMartin wants to merge 2 commits into
Conversation
added 2 commits
August 8, 2026 11:37
…Runner A session service that buffers writes has no defined point at which to drain. adk-python gives it one: a default no-op BaseSessionService.flush(). Add the same hook here and call it in the Runner's invocation teardown, after the toolsets close.
Pin the four invariants: the Runner drains once per invocation, after the last appendEvent, on the error path, and before runEphemeral deletes the session. A real buffering subclass proves the hook works end to end.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
N/A
Problem: A session service that batches event writes has no defined point at which to drain its buffer.
adk-jsoffers no hook, and theRunnernever signals the end of an invocation to the session service.adk-pythonhas this hook andadk-jsdoes not, so this is a cross-language parity gap.Solution: Add a concrete, default no-op
flush()toBaseSessionService, and await it in thefinallyofRunner.runAsync, after the toolsets close.adk-pythoncallsflush()fromRunner.close()(src/google/adk/runners.py);adk-jshas noRunner.close(), and therunAsyncteardown is whereadk-jsalready performs the toolset cleanup thatadk-pythonperforms inclose(). Draining per invocation is a stricter contract than draining at shutdown, and it gives the hook a caller today. No shipped session service overridesflush(), so nothing observable changes:InMemorySessionService,DatabaseSessionServiceandVertexAiSessionServiceall write synchronously.Parity notes: the method name, the no-op default and the position after
appendEventfollowsrc/google/adk/sessions/base_session_service.py. The call site is the one deliberate deviation, explained above. The Pythonif self.session_serviceguard is dropped becauseRunner.sessionServiceis a required field here.Collision check: I listed the 400 open PRs on this fork and read the diffs of every adjacent one. No PR adds
flush. #711, #616 and #609 also createcore/test/sessions/base_session_service_test.ts, so whichever merges second needs a trivial add/add resolution. #782 and #716 touchrunner.tsin other methods.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.
Six new cases in
core/test/runner/runner_test.ts(newdescribe, no existing block edited) and two in the newcore/test/sessions/base_session_service_test.ts. They pin: one drain per completed invocation, the drain after the lastappendEvent, one drain per invocation rather than per runner, a drain on the error path, a drain beforerunEphemeraldeletes the session, and a real buffering subclass whose buffer is empty and whose events are written when the invocation ends.Coverage: both new source lines are covered.
core/src/runner/runner.ts:457records 36 hits and theflush()body incore/src/sessions/base_session_service.tsrecords 1, measured with--coverage.reporter=jsonover the two targeted files.Proof the tests can fail. I deleted
await this.sessionService.flush();fromrunner.tsand re-ran; all six runner cases failed:I also moved the call from the
finallyto the top ofrunAsync, upstream of the agent loop. Only the ordering case failed, which shows it pins order and not merely presence:Finally I changed the base body to
throw new Error('x'). Both base cases failed:Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any necessary setup or configuration.
There is no user-visible behaviour to exercise by hand, because no shipped service buffers. To confirm the extension point by hand, subclass
InMemorySessionServicewith aflush()that increments a counter, drive it throughrunner.runEphemeral(...), and read the counter. It reads 1. Thedrains a buffering session service by the end of the invocationtest is the automated form of this, and it uses a realRunnerand a real subclass with no mocks.Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.
CI note
The first
run-tests (windows-latest)job failed oncore/test/code_executors/unsafe_local_code_executor_test.ts > should execute shell code and return stdoutwithTest timed out in 5000ms. That test spawns a shell and touches neither theRunnernor a session service, so this change cannot reach it. I re-ran the job with no code change and it passed. All six checks are green.